#include "clib_tcp_in.h"
#include "clib_sock.h"
#include "clib_stack.h"
#include "clib_tuple_hash.h"
#include "clib_tcp_buffer.h"

#define socket_list_add_timeout(ctx,sock,ts) 	\
	do { 										\
		if((ctx)->time_out > 0) {				\
			if(!(sock)->on_timeout_list) {		\
				clib_queue_insert_tail(&(ctx)->timeout_list,&(sock)->timeout_list); \
			} else {																\
				clib_queue_del(&(sock)->timeout_list);								\
				clib_queue_insert_tail(&(ctx)->timeout_list,&(sock)->timeout_list); \
				(sock)->on_timeout_list = true;									 	\
			}																	 	\
			(sock)->cur_time = (ts);											 	\
		}																		 	\
	} while(0)

static i32_t
clib_tcp_check_seq(stack_ctx_t *ctx,
                   clib_sock_t* sock,int payloadlen,u32_t seq)
{
	/** TODO 考虑数据回绕 **/
	tcp_stream_t* stream = &sock->tcp_stream;

	if(payloadlen == 0 && stream->rcv_wnd == 0)
	{
		if(seq != stream->rcv_nxt)
		{
			return rn_error;
		}
	}

	if(payloadlen != 0 && stream->rcv_wnd == 0)
	{
		return rn_error;
	}

	if(CLIB_TCP_CMP_SEQ(seq + payloadlen,stream->rcv_nxt) < 0) {
		return rn_error;
	}

	if(CLIB_TCP_CMP_SEQ(seq + payloadlen,stream->rcv_nxt + stream->rcv_wnd) >= 0)
	{
		return rn_error;
	}
	/** TODO 更新 rcv_nxt **/
	if(seq == stream->rcv_nxt)
	{
		stream->rcv_nxt = seq + payloadlen;
	}
	
	return rn_ok;
}

static i32_t 
clib_tcp_check_ack(stack_ctx_t *ctx, clib_sock_t* sock, u32_t ack) 
{
	tcp_stream_t* stream = &sock->tcp_stream;
	//An old duplicate ACK has been received
	if(CLIB_TCP_CMP_SEQ(ack, stream->snd_una) < 0) {
		/** TODO An old duplicate ACK has been received **/
		return rn_error;
	}

	if(CLIB_TCP_CMP_SEQ(ack, stream->snd_nxt) > 0) {
		/** TODO 错误 **/
		return rn_error;
	}
	/** TODO 处理确认的数据 ack 数据合规性检查 **/

	return rn_ok;
}

static i32_t 
clib_tcp_process_fin(stack_ctx_t *ctx, clib_sock_t* sock) 
{
	/** TODO 处理fin **/
	return rn_ok;
}

static i32_t 
clib_tcp_process_rst(stack_ctx_t *ctx, clib_sock_t* sock) 
{
	/** TODO 处理fin **/
	return rn_ok;
}

static inline i32_t
process_tcp_payload(stack_ctx_t *ctx,clib_sock_t* sock,uint32_t cur_ts,
					uint32_t seq,u08_t* data,i32_t data_len);

static inline void 
clib_tcp_st_listen(stack_ctx_t *ctx, u32_t cur_ts, 
		clib_sock_t* sock, struct tcphdr* tcph) {
	/** TCP 监听被动打开连接处理 **/
	if (tcph->th_flags == TH_SYN) {
		if (sock->tcp_stream.tcp_state == TCP_ST_LISTEN)
			sock->tcp_stream.rcv_nxt++;
		sock->tcp_stream.tcp_state = TCP_ST_SYN_RCVD;
		sock->tcp_stream.irs = tcph->seq;
		/** TODO 对于的socket acpt_listxxx **/
		clib_queue_del(&sock->list);
		clib_queue_insert_tail(&ctx->acpt_list,&sock->list);
		sock->on_acpt_list = 0;
		ctx->acpt_n++;
		/** TODO 发送 (syn/ack) **/
	} else {
		/** TODO 出错处理 **/
	}
}

static inline void 
clib_tcp_st_syn_sent(stack_ctx_t *ctx, u32_t cur_ts, 
		clib_sock_t* sock, const struct iphdr* iph, struct tcphdr* tcph,
		u32_t seq, u32_t ack_seq, i32_t payloadlen, u16_t window)
{
	/** TODO 处理接受 SYN/ACK 数据包 **/
	tcp_stream_t *stream = &sock->tcp_stream;
	if(tcph->th_flags != (TH_SYN | TH_SYN)) {
		/** TODO rst 相关处理 **/
	}

	if(tcph->ack) {
		stream->irs = seq;
		if(ack_seq != (stream->iss + 1)) {
			/** TODO 错误处理**/
		}
		stream->snd_una++;
		stream->snd_nxt = ack_seq;
		stream->snd_wnd = window;
		stream->snd_max_wnd = window;
		stream->rcv_nxt = seq + 1;
	}
	/** TODO 检测rto **/
	/** TODO 获取option **/
	// if(tcph->syn) {
	//  }
	if(CLIB_TCP_CMP_SEQ(stream->snd_una,stream->iss) > 0)
	{
		stream->snd_wl1 = seq;
		stream->snd_wl2 = ack_seq;
	}

	if(sock->on_ack_list) {
		clib_queue_del(&sock->list);
	}

	clib_queue_insert_tail(&ctx->ack_list,&sock->list);
	sock->on_ack_list = true;
	stream->tcp_state = TCP_ST_ESTABLISHED;

	socket_list_add_timeout(ctx,sock,cur_ts);
}

static inline void 
clib_tcp_st_syn_recv(stack_ctx_t *ctx, u32_t cur_ts,
		clib_sock_t* sock, struct tcphdr* tcph, u32_t seq, u32_t ack_seq) 
{
	/** TODO 处理接收 三次握手最后 ACK 数据包 **/
	clib_sock_t *listen;
	u32_t prior_cwnd;
	tcp_stream_t* stream = &sock->tcp_stream;
	int ret;
	if (tcph->ack) {

		/* check if ACK of SYN */
		if (ack_seq != stream->iss + 1) {
			/** TODO 出错处理 **/
			// CTRACE_ERROR("Stream %d (TCP_ST_SYN_RCVD): "
			// 		"weird ack_seq: %u, iss: %u\n", 
			// 		cur_stream->id, ack_seq, sndvar->iss);
			// TRACE_DBG("Stream %d (TCP_ST_SYN_RCVD): "
			// 		"weird ack_seq: %u, iss: %u\n", 
			// 		cur_stream->id, ack_seq, sndvar->iss);
			return;
		}
		stream->irs = seq;
		stream->snd_una++;
		stream->snd_nxt = ack_seq;
		//prior_cwnd = sndvar->cwnd;
		// sndvar->cwnd = ((prior_cwnd == 1)? 
		// 		(sndvar->mss * TCP_INIT_CWND): sndvar->mss);
		// TRACE_DBG("sync_recvd: updating cwnd from %u to %u\n", prior_cwnd, sndvar->cwnd);
		
		// //UpdateRetransmissionTimer(mtcp, cur_stream, cur_ts);
		//sndvar->nrtx = 0;
		stream->rcv_nxt = stream->irs + 1;
		//RemoveFromRTOList(mtcp, cur_stream);

		stream->tcp_state = TCP_ST_ESTABLISHED;
		//if(){}
		/** TODO 放进监听队列 **/
		//TRACE_STATE("Stream %d: TCP_ST_ESTABLISHED\n", cur_stream->id);
		/* update listening socket */
		// listener = (struct tcp_listener *)ListenerHTSearch(mtcp->listeners, &tcph->dest);
		listen = clib_tuple_hash_table_search(ctx->listen_table,&tcph->dest, 1);
		if(listen) {
			clib_queue_insert_tail(&listen->tcp_listen.accept,&sock->list);
			sock->on_acpt_list = true;
			listen->tcp_listen.accept_n++;
		} else {
			/** TODO 出错处理 **/
			return ;
		}
		// ret = StreamEnqueue(listener->acceptq, cur_stream);
		// if (ret < 0) {
		// 	TRACE_ERROR("Stream %d: Failed to enqueue to "
		// 			"the listen backlog!\n", cur_stream->id);
		// 	cur_stream->close_reason = TCP_NOT_ACCEPTED;
		// 	cur_stream->state = TCP_ST_CLOSED;
		// 	TRACE_STATE("Stream %d: TCP_ST_CLOSED\n", cur_stream->id);
		// 	AddtoControlList(mtcp, cur_stream, cur_ts);
		// }
		// //TRACE_DBG("Stream %d inserted into acceptq.\n", cur_stream->id);
		// if (CONFIG.tcp_timeout > 0)
		// 	AddtoTimeoutList(mtcp, cur_stream);
		socket_list_add_timeout(ctx,sock,cur_ts);
		// if(ctx->time_out > 0) {
		// 	if(!sock->on_timeout_list) {
		// 		clib_queue_insert_tail(&ctx->timeout_list,&sock->time_list);
		// 	} else {
		// 		clib_queue_del(&sock->time_list);
		// 		clib_queue_insert_tail(&ctx->timeout_list,&sock->time_list);
		// 		sock->on_timeout_list = true;
		// 	}
		// }

		if(listen->ep) {
			/** TODO *** 判断 listen 是否在 epoll 事件中  这处还需修改 **/
			if(listen->ev.events) {
				if(!listen->tcp_listen.on_ep) {
					clib_queue_insert_tail(&((clib_epoll_t*)listen->ep)->event_list,&listen->list);
					((clib_epoll_t*)listen->ep)->event_post++;
				}
			}
		}

		// /* raise an event to the listening socket */
		// if (listener->socket && (listener->socket->epoll & MTCP_EPOLLIN)) {
		// 	AddEpollEvent(mtcp->ep, 
		// 			MTCP_EVENT_QUEUE, listener->socket, MTCP_EPOLLIN);
		// }

	} else {
		/** TODO 是从新加入，还是 重新发送 syn/ack **/
		// TRACE_DBG("Stream %d (TCP_ST_SYN_RCVD): No ACK.\n", 
		// 		cur_stream->id);
		// /* retransmit SYN/ACK */
		// cur_stream->snd_nxt = sndvar->iss;
		// AddtoControlList(mtcp, cur_stream, cur_ts);
	}
}


static inline void
clib_tcp_st_established(stack_ctx_t *ctx, uint32_t cur_ts,
		clib_sock_t* sock, struct tcphdr* tcph, uint32_t seq, uint32_t ack_seq,
		uint8_t *payload, int payloadlen, uint16_t window) 
{
	tcp_stream_t* stream = &sock->tcp_stream;
	if (tcph->syn) {
		/** TODO socket 畸形syn 标记异常 **/
		return;
	}

	if(clib_tcp_check_seq(ctx, sock, payloadlen, seq) < 0) {
		/** TODO 错误处理 **/
		return ;
	}

	if (payloadlen > 0) {
		clib_tcp_buffer_recv_put_data(stream->recv_buffer, seq, payload, payloadlen);
		if(stream->recv_buffer->ready_len > 0) {
			/** TODO 加入到epoll队列 在刚加入到epoll 是主动轮询socket一次 **/
			if(sock->ep && sock->ev.events & CLIB_EPOLLIN) {
				
			}
		}
	}
	
	if (tcph->ack) {
		clib_tcp_check_ack(ctx, sock, ack_seq);
		clib_tcp_buffer_send_ack_date(stream->send_buffer,ack_seq);
	}

	if (tcph->fin) {
		/** TODO 结束处理 注意状态变化 **/
		// /* process the FIN only if the sequence is valid */
		// /* FIN packet is allowed to push payload (should we check for PSH flag)? */
		// if (seq + payloadlen == cur_stream->rcv_nxt) {
		// 	cur_stream->state = TCP_ST_CLOSE_WAIT;
		// 	TRACE_STATE("Stream %d: TCP_ST_CLOSE_WAIT\n", cur_stream->id);
		// 	cur_stream->rcv_nxt++;
		// 	AddtoControlList(mtcp, cur_stream, cur_ts);

		// 	/* notify FIN to application */
		// 	RaiseReadEvent(mtcp, cur_stream);
		// } else {
		// 	EnqueueACK(mtcp, cur_stream, cur_ts, ACK_OPT_NOW);
		// 	return;
		// }
	}
}


static inline void 
clib_tcp_st_close_wait(stack_ctx_t *ctx, uint32_t cur_ts,
		clib_sock_t* sock, struct tcphdr* tcph, uint32_t seq, uint32_t ack_seq) 
{
	if(clib_tcp_check_seq(ctx,sock,0,seq) == rn_error) {
		return ;
	}
	if(tcph->rst) {
		sock->tcp_stream.tcp_state = TCP_ST_CLOSED;
	}
	/** TODO 清楚所有所在的链表 **/
	clib_queue_insert_tail(&ctx->free_list,&sock->list);
	/** TODO 添加到关闭链表 **/
}

static inline void
clib_tcp_st_fin_wait1(stack_ctx_t *ctx, uint32_t cur_ts,clib_sock_t* sock, 
		struct tcphdr* tcph,uint32_t seq, uint32_t ack_seq) 
{
	tcp_stream_t* stream = &sock->tcp_stream;

	if(CLIB_TCP_CMP_SEQ(stream->snd_nxt,ack_seq) == 0)
	{

	}

	if(CLIB_TCP_CMP_SEQ(stream->rcv_nxt,seq) == 0)
	{

	}
	if(tcph->ack) {
		stream->tcp_state = TCP_ST_FIN_WAIT2;
	}
	if(tcph->fin) {
		stream->rcv_nxt++;
		/** TODO  fin 允许带载荷 **/
		stream->tcp_state = TCP_ST_CLOSING;
	}
}

static inline void
clib_tcp_st_fin_wait2(stack_ctx_t *ctx, uint32_t cur_ts,clib_sock_t* sock, 
		struct tcphdr* tcph,uint32_t seq, uint32_t ack_seq) 
{
	tcp_stream_t* stream = &sock->tcp_stream;
	if(CLIB_TCP_CMP_SEQ(stream->snd_nxt,ack_seq) == 0)
	{

	}
	
	if(CLIB_TCP_CMP_SEQ(stream->snd_nxt,ack_seq) == 0)
	{

	}
	/** TODO **/
	if(tcph->fin) {
		/** 发送最后的 ack **/
		stream->tcp_state = TCP_ST_TIME_WAIT;
	}
	return ;
}

static inline void
clib_tcp_st_closing(stack_ctx_t *ctx, uint32_t cur_ts,clib_sock_t* sock, 
		struct tcphdr* tcph,uint32_t seq, uint32_t ack_seq) 
{
	tcp_stream_t* stream = &sock->tcp_stream;

	if(CLIB_TCP_CMP_SEQ(stream->snd_nxt, ack_seq) == 0) {

	}

	if(CLIB_TCP_CMP_SEQ(stream->rcv_nxt, seq) == 0) {

	}

	if(tcph->ack) {
		stream->tcp_state = TCP_ST_TIME_WAIT;
		/** TODO 加入到time wiat **/
	}
}

static inline void
clib_tcp_st_timewait(stack_ctx_t *ctx, uint32_t cur_ts,clib_sock_t* sock, 
		struct tcphdr* tcph,uint32_t seq, uint32_t ack_seq)
{
	tcp_stream_t* stream = &sock->tcp_stream;

	if(tcph->fin) {
		//stream->tcp_state = TCP_ST_TIME_WAIT;
		/** TODO 加入到time wiat **/
	}
}

i32_t 
clib_process_ipv4_tcp_packet(stack_ctx_t *ctx,ip4_hdr_t* ipv4,i32_t ip_len,u64_t cur_ts)
{
    tcp_hdr_t *tcph  = (tcp_hdr_t*) ((u08_t*)ipv4 + (ipv4->ihl << 2));
    u08_t *payload  = (u08_t *)tcph + (tcph->doff << 2);
    i32_t payload_len = ip_len - (payload - (u08_t *)ipv4);

    tcp_stream_t *stream;
    clib_sock_t       *sock;

	u32_t seq     = ntohl(tcph->seq);
	u32_t ack_seq = ntohl(tcph->ack_seq);
	u16_t window  = ntohs(tcph->window);

    ipv4_tuple_t      tuple;
    tuple.l_addr = ipv4->daddr;
    tuple.r_addr = ipv4->saddr;
	tuple.l_port = tcph->th_dport;
    tuple.r_port = tcph->th_sport;
    tuple.procotol = 0x06;
	
    /** TODO 查找socket **/
	sock = clib_tuple_hash_table_search(ctx->hash_table,&tuple,1);
    if(!sock)
    {
		if(!(tcph->th_flags == TH_SYN)) {
			return rn_error;
		}
		/** TODO 查找 监听套接字 **/
        sock = clib_get_sock_new_by_stack(ctx);
		sock->ipv4 = 1;
		//TODO socket ipv4 init
        //sock_init();
        clib_tuple_hash_table_insert(ctx->hash_table,&tuple);
    }
	sock->cur_time = cur_ts;
    stream = &sock->tcp_stream;
    /** TODO rset **/
    if(stream->tcp_state > TCP_ST_SYN_RCVD) {
		/** TODO 思考 **/
        if(clib_tcp_check_seq(ctx, sock, payload_len, seq) == rn_error) {
			/** TODO 出错处理 **/
		}
    }

    switch (stream->tcp_state) 
	{
	case TCP_ST_LISTEN:
		clib_tcp_st_listen(ctx,cur_ts,sock,tcph);
		break;

	case TCP_ST_SYN_SENT:
		clib_tcp_st_syn_sent(ctx,cur_ts,sock,ipv4,tcph,seq,ack_seq,payload_len,window);
		break;

	case TCP_ST_SYN_RCVD:
		/** syn/ack 丢包的情况 **/
		if(tcph->th_flags == TH_SYN && seq == sock->tcp_stream.irs) {
			/** TODO  **/
			//clib_tcp_st_listen(ctx,cur_ts,sock,tcph);
		} else {
			clib_tcp_st_syn_recv(ctx, cur_ts, sock, tcph, seq, ack_seq);
			if(payload_len > 0 && stream->tcp_state == TCP_ST_ESTABLISHED) {
				clib_tcp_st_established(ctx, cur_ts, sock, tcph, seq, ack_seq, payload, payload_len, window);
			}
		}
		break;

	case TCP_ST_ESTABLISHED:
		clib_tcp_st_established(ctx, cur_ts, sock, tcph, seq, ack_seq, payload, payload_len, window);
		break;

	case TCP_ST_CLOSE_WAIT:
		clib_tcp_st_close_wait(ctx, cur_ts, sock, tcph, seq, ack_seq);
		break;

	case TCP_ST_LAST_ACK:
		// Handle_TCP_ST_LAST_ACK(mtcp, cur_ts, iph, ip_len, cur_stream, tcph, 
		// 		seq, ack_seq, payloadlen, window);
		break;
	
	case TCP_ST_FIN_WAIT1:
		clib_tcp_st_fin_wait1(ctx, cur_ts, sock, tcph, seq, ack_seq);
		break;

	case TCP_ST_FIN_WAIT2:
		clib_tcp_st_fin_wait2(ctx, cur_ts, sock, tcph, seq, ack_seq);
		break;

	case TCP_ST_CLOSING:
		clib_tcp_st_closing(ctx, cur_ts, sock, tcph, seq, ack_seq);
		break;

	case TCP_ST_TIME_WAIT:
		clib_tcp_st_timewait(ctx, cur_ts, sock, tcph, seq, ack_seq);
		/* the only thing that can arrive in this state is a retransmission 
		   of the remote FIN. Acknowledge it, and restart the 2 MSL timeout */
		// if (cur_stream->on_timewait_list) {
		// 	RemoveFromTimewaitList(mtcp, cur_stream);
		// 	AddtoTimewaitList(mtcp, cur_stream, cur_ts);
		// }
		// AddtoControlList(mtcp, cur_stream, cur_ts);
		break;

	case TCP_ST_CLOSED:
		break;

	}

    return rn_ok;
}

i32_t clib_process_ipv6_tcp_packet(stack_ctx_t *ctx,ip6_hdr_t* ipv4,i32_t ip_len,u64_t cur_ts)
{
    return rn_error;
}
